package com.lry.basic.netty.demo1;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.*;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

import java.net.InetSocketAddress;

/**
 * @author:刘仁有
 * @desc:
 * @email:953506233@qq.com
 * @data:2019/9/11
 */
public class EchoServer {
    private final int port;

    public EchoServer(int port) {
        this.port = port;
    }

    public static void main(String[] args) throws InterruptedException {
        new EchoServer(9999).start();
    }

    private void start() throws InterruptedException {
        // 入门案例使用Reactor单线程模型
        // 接收客户端的TCP连接；向通信对端发送消息请求或者应答消息；
        EventLoopGroup group = new NioEventLoopGroup();
        try {
        //服务器启动类，把所有组件串起来
        ServerBootstrap server = new ServerBootstrap();
        server.group(group)
                .channel(NioServerSocketChannel.class)
                .localAddress(new InetSocketAddress(port))
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    //Handler主要是做编解码和业务逻辑处理
                    //为什么要做编解码，因为数据在网络上都是字节传输的(也可以说二进制，只不过粒度小点而已)
                    //而我们接收数据期望收到的可不是字节，而是基本数据类型或者对象。所以要做编解码
                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        socketChannel.pipeline().addLast( new LengthFieldPrepender(4,false));
                        socketChannel.pipeline().addLast(new LengthFieldBasedFrameDecoder(1024,0,4,0,4));
                        socketChannel.pipeline().addLast("decoder", new StringDecoder());
                        socketChannel.pipeline().addLast("encoder", new StringEncoder());
                        socketChannel.pipeline().addLast(new EchoServerHandler());
                    }
                });
        ChannelFuture future = server.bind().sync();

        System.out.println(EchoServer.class.getName() + " started and listen on " + future.channel().localAddress());
        future.channel().closeFuture().sync();
        } finally {
            group.shutdownGracefully().sync();
        }
    }
}
